// 电磁锁控制系统（仅使用NO信号检测）
// 使用串口通信控制继电器和监测门状态

const int relayPin = 8;      // 继电器控制引脚
const int noPin = 2;         // NO（常开）信号引脚

bool doorLocked = false;     // 电磁锁状态
bool doorOpened = false;     // 门状态
unsigned long lastDoorChange = 0;  // 上次门状态变化时间
const unsigned long DOOR_DEBOUNCE_TIME = 500;  // 防抖动时间（毫秒）

void setup() {
  // 初始化引脚
  pinMode(relayPin, OUTPUT);
  pinMode(noPin, INPUT_PULLUP); // 使用内部上拉电阻

  // 初始状态：电磁锁关闭
  digitalWrite(relayPin, LOW);

  // 初始化串口通信
  Serial.begin(9600);

  // 初始状态检测
  checkDoorStatus(true);
}

void loop() {
  // 检查门状态
  checkDoorStatus(false);

  // 处理串口命令
  if (Serial.available() > 0) {
    String command = Serial.readStringUntil('\n');
    command.trim();
    processCommand(command);
  }

  delay(100); // 短暂延迟
}

void checkDoorStatus(bool force) {
  // 读取NO信号状态，进行多次采样以提高稳定性
  int sampleCount = 5;
  int highCount = 0;
  
  for (int i = 0; i < sampleCount; i++) {
    if (digitalRead(noPin) == HIGH) {
      highCount++;
    }
    delay(10); // 短暂延迟
  }
  
  // 如果超过一半的采样为HIGH，则认为门是打开的
  bool currentDoorState = (highCount > sampleCount / 2);

  // 调试信息：显示原始信号状态
  if (force) {
    Serial.print("DEBUG: 原始信号采样 - HIGH: ");
    Serial.print(highCount);
    Serial.print("/");
    Serial.print(sampleCount);
    Serial.print(", 判断结果: ");
    Serial.println(currentDoorState ? "OPEN" : "CLOSE");
  }

  // 防抖动处理：只有在状态真正改变且距离上次变化超过防抖动时间才更新
  unsigned long currentTime = millis();
  if ((currentDoorState != doorOpened || force) && 
      (force || (currentTime - lastDoorChange) > DOOR_DEBOUNCE_TIME)) {
    
    doorOpened = currentDoorState;
    lastDoorChange = currentTime;

    if (doorOpened) {
      Serial.println("OPEN");
    } else {
      Serial.println("CLOSE");
    }
  }
}

void processCommand(String command) {
  if (command.equalsIgnoreCase("LOCK") || command.equalsIgnoreCase("1")) {
    lockDoor();
  } else if (command.equalsIgnoreCase("UNLOCK") || command.equalsIgnoreCase("0")) {
    unlockDoor();
  } else if (command.equalsIgnoreCase("STATUS") || command.equalsIgnoreCase("2")) {
    sendStatus();
  } else {
    Serial.println("UNKNOWN: " + command);
  }
}

void lockDoor() {
  digitalWrite(relayPin, HIGH);
  doorLocked = true;
  Serial.println("LOCK");
  // 等待锁动作完成
  delay(500);
}

void unlockDoor() {
  digitalWrite(relayPin, LOW);
  doorLocked = false;
  Serial.println("UNLOCK");
  // 等待锁动作完成
  delay(500);
}

void sendStatus() {
  delay(200);
  Serial.println(doorLocked ? "LOCK" : "UNLOCK");
  delay(200);
  Serial.println(doorOpened ? "OPEN" : "CLOSE");
}